package com.jabex.core.bussines;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.jabex.common.exceptions.ErrorFunctionalException;
import com.jabex.common.exceptions.ErrorOperationalException;
import com.jabex.common.exceptions.WarningFunctionalException;
import com.jabex.common.to.ImagesTO;
import com.jabex.common.to.MessageTO;
import com.jabex.common.to.PricesTO;
import com.jabex.common.to.ProductTO;
import com.jabex.common.util.Constants;
import com.jabex.persistence.dao.IProductDAO;
import com.jabex.persistence.model.Images;
import com.jabex.persistence.model.Prices;
import com.jabex.persistence.model.Product;

/**
 * Created by jaugusto on 15/09/14. *
 */
@Service(value = ProductBp.SERVICE_NAME)
@Scope("request")
public class ProductBp implements IProductBp {
	static private Logger logger = Logger.getLogger(ProductBp.class);

	@Autowired
	@Qualifier(IProductDAO.MODEL_NAME)
	private IProductDAO productDao;

	@Override
	@Transactional
	public MessageTO insertProduct(ProductTO productTO) throws WarningFunctionalException, ErrorFunctionalException, ErrorOperationalException {
		List<Images> imagesList = new ArrayList<Images>();
		List<Prices> pricesList = new ArrayList<Prices>();
		MessageTO messageTO;
		try {
			Product product = new Product(productTO);

			if (productTO.getImages() != null) {
				for (ImagesTO imagesTO : productTO.getImages()) {
					Images images = new Images(imagesTO);
					imagesList.add(images);
				}
			}
			if (productTO.getPrices() != null) {
				for (PricesTO pricesTO : productTO.getPrices()) {
					Prices prices = new Prices(pricesTO);
					pricesList.add(prices);
				}
			}
			product.setImages(imagesList);
			product.setPrices(pricesList);
			messageTO = productDao.insertProduct(product);
		} catch (WarningFunctionalException e) {
			logger.warn(e.getMessage());
			throw new WarningFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.INSERT.name(), null);
		} catch (ErrorFunctionalException e) {
			logger.error(e.getMessage());
			throw new ErrorFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.INSERT.name(), null);
		} catch (Exception e) {
			logger.fatal(e.getMessage());
			throw new ErrorOperationalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage() + e.getCause(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.INSERT.name(), null);
		}
		return messageTO;
	}

	@Override
	@Transactional
	public MessageTO deleteProduct(int id) throws WarningFunctionalException, ErrorFunctionalException, ErrorOperationalException {
		MessageTO messageTO;
		try {
			messageTO = productDao.deleteProduct(id);
		} catch (WarningFunctionalException e) {
			logger.warn(e.getMessage());
			throw new WarningFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.DELETE.name(), null);
		} catch (ErrorFunctionalException e) {
			logger.error(e.getMessage());
			throw new ErrorFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.DELETE.name(), null);
		} catch (Exception e) {
			logger.fatal(e.getMessage());
			throw new ErrorOperationalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.DELETE.name(), null);
		}
		return messageTO;
	}

	@Override
	@Transactional
	public MessageTO updateProduct(ProductTO productTO) throws WarningFunctionalException, ErrorFunctionalException, ErrorOperationalException {
		MessageTO messageTO;
		try {
			Product product = new Product(productTO);
			messageTO = productDao.updateProduct(product);
		} catch (WarningFunctionalException e) {
			logger.warn(e.getMessage());
			throw new WarningFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.UPDATE.name(), null);
		} catch (ErrorFunctionalException e) {
			logger.error(e.getMessage());
			throw new ErrorFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.UPDATE.name(), null);
		} catch (Exception e) {
			logger.fatal(e.getMessage());
			throw new ErrorOperationalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.UPDATE.name(), null);
		}
		return messageTO;
	}

	@Override
	@Transactional
	public ProductTO getProductById(int id) throws WarningFunctionalException, ErrorFunctionalException, ErrorOperationalException {
		ProductTO productTO = new ProductTO();
		List<ImagesTO> imagesTOList = new ArrayList<ImagesTO>();
		List<PricesTO> pricesTOList = new ArrayList<PricesTO>();
		try {
			Product product = productDao.getObjectById(String.valueOf(id));
			productTO.setCreateDate(LocalDate.parse(product.getCreateDate().toString()));
			productTO.setDescription(product.getDescription());
			productTO.setName(product.getName());
			productTO.setTypeProduct(product.getDescription());
			for (Images images : product.getImages()) {
				ImagesTO imagesTO = new ImagesTO();
				imagesTO.setIsActive(images.getIsActive());
				imagesTO.setCreateDate(new LocalDate(images.getCreateDate()));
				imagesTO.setCreateTime(new LocalDateTime(images.getCreateDate().getTime()));
				imagesTO.setName(images.getName());
				imagesTO.setDescription(images.getDescription());
				imagesTO.setImgByte(images.getImgByte());
				imagesTO.setTypeImage(images.getTypeImage());
				imagesTO.setUrlImage(images.getUrlImage());
				imagesTOList.add(imagesTO);
			}
			for (Prices prices : product.getPrices()) {
				PricesTO pricesTO = new PricesTO();
				pricesTO.setCommission(prices.getCommission());
				pricesTO.setCurrency(prices.getCurrency());
				pricesTO.setPrice(prices.getPrice());
				pricesTO.setPriceBuy(prices.getPriceBuy());
				pricesTO.setPriceSell(prices.getPriceSell());
				pricesTO.setTaxCommission(prices.getTaxCommission());
				pricesTO.setTaxPrice(prices.getTaxPrice());
				pricesTOList.add(pricesTO);
			}
			productTO.setPrices(pricesTOList);
			productTO.setImages(imagesTOList);
		} catch (WarningFunctionalException e) {
			logger.warn(e.getMessage());
			throw new WarningFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.GET.name(), null);
		} catch (ErrorFunctionalException e) {
			logger.error(e.getMessage());
			throw new ErrorFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.GET.name(), null);
		} catch (Exception e) {
			logger.fatal(e.getMessage());
			throw new ErrorOperationalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.GET.name(), null);
		}
		return productTO;
	}

	@Override
	@Transactional
	public List<ProductTO> getAllProduct() throws WarningFunctionalException, ErrorFunctionalException, ErrorOperationalException {
		List<ProductTO> productTOList = new ArrayList<ProductTO>();
		try {
			List<Product> allProduct = productDao.getAllProduct();
			for (Product product : allProduct) {
				ProductTO productTO = new ProductTO();
				productTO.setName(product.getName());
				productTO.setDescription(product.getDescription());
				productTO.setCreateDate(new LocalDate(product.getCreateDate()));
				productTO.setCreateTime(new LocalDateTime(product.getCreateDate().getTime()));
				productTO.setIsActive(product.getIsActive());
				productTOList.add(productTO);
			}

		} catch (WarningFunctionalException e) {
			logger.warn(e.getMessage());
			throw new WarningFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.GET.name(), null);
		} catch (ErrorFunctionalException e) {
			logger.error(e.getMessage());
			throw new ErrorFunctionalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), null, Constants.TYPE_TRANSACTION.GET.name(), null);
		} catch (Exception e) {
			logger.fatal(e.getMessage());
			throw new ErrorOperationalException(Constants.NAME_APP_MANAGER, Constants.CODE_APP_MANAGER, e.getMessage(),
					Constants.TYPE_ORIGIN.DESKTOP.name(), Constants.TYPE_CHANNELS.WEB.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.GET.name(), null);
		}
		return productTOList;
	}
}
